package source;

import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

import client.controlpanel.Configuration;

public class RSInheritance extends RS232Source implements DataSource,
		SerialPortEventListener {
	private List<DataSourceListener> listeners;
	boolean portChecked = false;
	int currentLength = 0;
	int totalLength = 0;
	public static int baudRate = 9600;
	public static String portName = "COM1";
	byte[] readBuffer = new byte[46];
	static CommPortIdentifier portId;
	@SuppressWarnings("rawtypes")
	static Enumeration portList;
	InputStream inputStream;
	SerialPort serialPort;
	Thread readThread;

	public RS232Source() {
		listeners = new ArrayList<DataSourceListener>();
	}

	@Override
	public void addListner(DataSourceListener listener) {
		listeners.add(listener);
	}

	@Override
	public void startGatheringData() {
		Configuration config = Configuration.getInstance();
		portName = config.getPortName();
		checkPort();
		startReceiving();
	}

	public void serialEvent(SerialPortEvent event) {
		switch (event.getEventType()) {
		case SerialPortEvent.BI:
		case SerialPortEvent.OE:
		case SerialPortEvent.FE:
		case SerialPortEvent.PE:
		case SerialPortEvent.CD:
		case SerialPortEvent.CTS:
		case SerialPortEvent.DSR:
		case SerialPortEvent.RI:
		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			break;
		case SerialPortEvent.DATA_AVAILABLE:
			try {
				while (inputStream.available() > 0) {

					currentLength = inputStream.available();
					inputStream.read(readBuffer, totalLength, currentLength);
					totalLength += currentLength;

					if (endOfInformation(new String(readBuffer,
							totalLength - 1, 1))) {
						RawDataImpl data = new RawDataImpl();
						data.setData(new String(readBuffer, 0, totalLength - 2));
						notifyObservers(data);

						totalLength = 0;
						currentLength = 0;
					}

				}

			} catch (IOException e) {
			}

			break;
		}
	}

	public boolean checkPort() {
		portList = CommPortIdentifier.getPortIdentifiers();
		while (portList.hasMoreElements()) {
			portId = (CommPortIdentifier) portList.nextElement();
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				if (portId.getName().equals(portName)) {
					portChecked = true;
					return true;
				}
			}
		}
		return false;
	}

	public List<String> getSerialPorts() {
		ArrayList<String> ports = new ArrayList<String>();

		portList = CommPortIdentifier.getPortIdentifiers();
		while (portList.hasMoreElements()) {
			portId = (CommPortIdentifier) portList.nextElement();
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				ports.add(portId.getName());
			}
		}

		// Hotfix for testing (IA-64 problems)
		// ports.add("COM1");
		// ports.add("COM2");
		return ports;
	}

	public void startReceiving() {
		if (portChecked) {
			try {
				serialPort = (SerialPort) portId.open("RS232", 2000);
			} catch (PortInUseException e) {
				return;
			}

			try {
				inputStream = serialPort.getInputStream();
			} catch (IOException e) {
				return;
			}

			try {
				serialPort.addEventListener(this);
			} catch (TooManyListenersException e) {
				return;
			}

			serialPort.notifyOnDataAvailable(true);

			try {
				serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8,
						SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
			} catch (UnsupportedCommOperationException e) {
				return;
			}

			readThread = new Thread(this);
			readThread.start();
		}
	}

	public void stopReceiving() {
		try {
			if (portId.isCurrentlyOwned()) {
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (IOException ex) {
						ex.printStackTrace();
					}
				}
				serialPort.removeEventListener();
				if (serialPort != null) {
					serialPort.close();
				}
			} else {
			}
		} catch (NullPointerException e) {
		}

	}

	private void notifyObservers(RawData data) {
		for (DataSourceListener listener : listeners) {
			if (listener != null) {
				listener.notify(data);
			}
		}
	}

	private boolean endOfInformation(String s) {
		char c = s.charAt(0);
		int asciiCode = (int) c;
 if (true) {
 c = 5;
 }
		if (asciiCode == 10) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void stopGatheringData() {
		stopReceiving();
	}

	@Override
	public String getConfigId() {
		return "RS232 DataSource";
	}

}
